Android Native binder 通信实例 | 您所在的位置:网站首页 › 安卓 binder 使用实例 › Android Native binder 通信实例 |
最近在考虑android native 跨进程通信问题,之前用hidl实现过system进程和vendor进程通信,这次考虑用aidl 在native层实现跨进程通信,了解到binder通信最大发送数据是1MB , 想要测试看看跨进程大数据通信吞吐率能达到多少。 下面开始上代码。 1 定义接口AIDL首先是定义接口,需要先想好我们需要定义哪些通信接口。把想要提供的接口、callback 定义好,后续通过继承接口类实现具体功能。aidl文件需要以其包名的路径格式放在代码工程目录的:aidl/com/test/speedtest 目录下面: ISpeedTestService.aidl : package com.test.speedtest; import com.test.speedtest.ISpeedTestCallback; // 在aidl中使用到其他aidl定义的接口需要import interface ISpeedTestService { oneway void startSpeedTest(); // oneway 修饰使得耗时的调用不阻塞当前线程,直接返回 void setSpeedTestCb(ISpeedTestCallback cb); } ISpeedTestCallback.aidl: package com.test.speedtest; interface ISpeedTestCallback { oneway void onSpeedTestDone(in float speed); // callback异步返回测试结果 oneway void onSend(in byte[] buf, int length); //通过callback接口给client发数据 } aidl文件在编译时会自动生成源文件,路径在out/target/product/xxx/obj/EXECUTABLES/SpeedTestClient_intermediates/aidl-generated 目录下,里面会有头文件和cpp文件,我们只需要后面继承里面的类重新实现里面的逻辑即可。 不知道具体路径在哪里可以通过find 命令去查找, 比如: find . -name ISpeedTestService.h 我们只需要继承BnSpeedTestService 和 BnSpeedTestCallback 两个类即可,其他类都用自动生成的,不知道怎么继承自动生成的代码的话需要先找到自动生成代码,然后对着这两个类的实现重写类的实现。 2. 配置Android.mkaidl文件定义好了后配置Android.mk 文件或者Android.bp, 这里以Android.mk为例: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := libcutils \ libutils \ libbinder \ #binder通信so库 liblog LOCAL_MODULE := SpeedTestService LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl LOCAL_SRC_FILES := $(call all-cpp-files-under, server/src) #包含service端cpp文件 LOCAL_SRC_FILES += $(call all-subdir-Iaidl-files, aidl) # 包含所有aidl文件 include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := libcutils \ libutils \ libbinder \ liblog LOCAL_MODULE := SpeedTestClient LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl LOCAL_SRC_FILES := $(call all-cpp-files-under, client/src) #包含client端cpp文件 LOCAL_SRC_FILES += $(call all-subdir-Iaidl-files, aidl) include $(BUILD_EXECUTABLE) 3. 实现Service端代码SPeedTestService.h: #ifndef SPEED_TEST_SERVICE_H #define SPEED_TEST_SERVICE_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "logUtils.h" using namespace android; using namespace std; using namespace com::test::speedtest; namespace com { namespace test { namespace speedtest { class SpeedTestService : public BnSpeedTestService { public: static sp getInstance(); ::android::binder::Status setSpeedTestCb(const ::android::sp& cb); ::android::binder::Status startSpeedTest(); private: atomic stoped; mutex mMutex; condition_variable finished; uint32_t count; sp mCallback; void startTimer(uint32_t interval); void startSendThread(); SpeedTestService(); ~SpeedTestService(); }; } // namespace speedtest } // namespace test } // namespace speedtest #endif /* SPEED_TEST_SERVICE_H */ SPeedTestService.cpp: #include #include "SpeedTestService.h" #define TAG "SpeedTestService" using namespace android; using namespace com::test::speedtest; namespace com { namespace test { namespace speedtest { ::android::binder::Status SpeedTestService::startSpeedTest() { startTimer(10000); // start a 10s timer thread startSendThread(); std::unique_lock lock(mMutex); finished.wait(lock); //counter speed ALOGD(TAG,"Recived finished cond"); float speed = count*512*8/10240; mCallback->onSpeedTestDone(speed); ALOGD(TAG, "send test result %.2f", speed); return ::android::binder::Status::ok(); } SpeedTestService:: SpeedTestService(): stoped(false), mCallback(nullptr), count(0) { } SpeedTestService:: ~SpeedTestService() { } void SpeedTestService:: startTimer(uint32_t interval) { ALOGD(TAG, "start timer ..."); if( stoped.load() ) { return; } std::thread([this, interval] () { std::this_thread::sleep_for(std::chrono::milliseconds(interval)); ALOGD(TAG, "sleep timer exited"); stoped.store(true); }).detach(); } void SpeedTestService::startSendThread() { if(mCallback == nullptr) { ALOGE(TAG, "callback is nullptr"); return; } ALOGD(TAG, "start send thread"); std::thread([=](){ std::vector vec(256*1024,'c'); while(!stoped.load()) { if(mCallback != nullptr) { mCallback->onSend(vec, vec.size()); count += 1; } } finished.notify_all(); ALOGD(TAG, "send thread finished"); }).detach(); } ::android::binder::Status SpeedTestService::setSpeedTestCb(const ::android::sp &cb) { mCallback = cb; return ::android::binder::Status::ok(); } sp SpeedTestService::getInstance() { return new SpeedTestService(); } } //namespace speedtest } //namespace test } //namespace com main.cpp: #include "SpeedTestService.h" #include int main(int argc, char* argv[]) { sp proc(ProcessState::self()); sp mService = SpeedTestService::getInstance(); if(mService == nullptr) { ALOGE("SpeedTestService", "failed to new service"); } status_t ret = defaultServiceManager()->addService(String16("com.test.speedtest.ISpeedTestService"), mService); ALOGD("SpeedTestService", "add service return %d", ret); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return 0; } 4. 实现客户端代码SpeedTestCallback.h: #ifndef SPEED_TEST_CALLBACK_H #define SPEED_TEST_CALLBACK_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "logUtils.h" using namespace android; using namespace std; using namespace com::test::speedtest; namespace com { namespace test { namespace speedtest { class SpeedTestCallback : public BnSpeedTestCallback { public: static sp getInstance(); virtual ::android::binder::Status onSpeedTestDone(float speed); virtual ::android::binder::Status onSend(const ::std::vector &buf, int32_t length); private: SpeedTestCallback(); ~SpeedTestCallback(); }; } // namespace speedtest } // namespace test } // namespace speedtest #endif /* SPEED_TEST_CALLBACK_H */ SpeedTestCallback.cpp: #include "SpeedTestCallback.h" #define TAG "SpeedTestCallback" namespace com { namespace test { namespace speedtest { SpeedTestCallback::SpeedTestCallback(){} SpeedTestCallback::~SpeedTestCallback(){} ::android::binder::Status SpeedTestCallback::onSpeedTestDone(float speed) { ALOGD(TAG, "Bn SpeedTestCallback : onSpeedTestDone %f", speed); return ::android::binder::Status::ok(); } ::android::binder::Status SpeedTestCallback::onSend(const ::std::vector &buf, int32_t length) { //ALOGD(TAG, "Bn SpeedTestCallback: received data lenth %d", length); return ::android::binder::Status::ok(); } sp SpeedTestCallback::getInstance() { return new SpeedTestCallback(); } } //namespace speedtest } //namespace test } //namespace com main.cpp: #include "SpeedTestService.h" #include "SpeedTestCallback.h" using namespace com::test::speedtest; #define TAG "SpeedTestClient" sp getService() { ALOGD(TAG,"get SpeedTestService..."); sp sm = defaultServiceManager(); if(sm == nullptr) { ALOGE(TAG, "failed to get service manager"); return nullptr; } sp binder = sm->getService(String16("com.test.speedtest.ISpeedTestService")); if(binder == nullptr) { ALOGE(TAG, "failed to get ISpeedTestService"); return nullptr; } sp service = interface_cast(binder); return service; } int main(int argc, char *argv[]) { sp proxy = getService(); if(proxy == nullptr){ ALOGE(TAG, "failed get binder service"); } proxy->setSpeedTestCb(SpeedTestCallback::getInstance()); proxy->startSpeedTest(); IPCThreadState::self()->joinThreadPool(); // 加入如到线程池中不让程序退出 return 0; } logUtils.h: #ifndef SPEED_TEST_UTILS_H #define SPEED_TEST_UTILS_H #include #define ALOGI(TAG, ...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) #define ALOGV(TAG, ...) __android_log_print(ANDROID_LOG_VERBOSE,TAG,__VA_ARGS__) #define ALOGD(TAG, ...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__) #define ALOGE(TAG, ...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) #define ALOGW(TAG, ...) __android_log_print(ANDROID_LOG_WARN,TAG,__VA_ARGS__) #define ALOGF(TAG, ...) __android_log_print(ANDROID_LOG_FATAL,TAG,__VA_ARGS__) #endif 5. 运行结果编译生成SpeedTestService 和 SpeedTestClient 两个bin文件,push到system/bin目录下,然后关闭sepolicy ,先执行./SpeedTestService , 再开一个终端执行./SpeedTestClient : 10-28 07:56:45.507 5183 5183 D SpeedTestService: add service return 0 10-28 07:56:52.574 5187 5187 D SpeedTestClient: get SpeedTestService... 10-28 07:56:52.581 5183 5184 D SpeedTestService: start timer ... 10-28 07:56:52.582 5183 5184 D SpeedTestService: start send thread 10-28 07:57:02.583 5183 5188 D SpeedTestService: sleep timer exited 10-28 07:57:02.584 5183 5189 D SpeedTestService: send thread finished 10-28 07:57:02.584 5183 5184 D SpeedTestService: Recived finished cond 10-28 07:57:02.584 5187 5187 D SpeedTestCallback: Bn SpeedTestCallback : onSpeedTestDone 6166.000000 10-28 07:57:02.584 5183 5184 D SpeedTestService: send test result 6166.00 |
CopyRight 2018-2019 实验室设备网 版权所有 |